package com.jichaoyun.service.util.TcpUtils;

import com.jichaoyun.dao.mapper.ComErrAlarmMapper;
import com.jichaoyun.model.entity.ComErrAlarm;
import com.jichaoyun.model.entity.Realdata;
import com.jichaoyun.model.entity.StationInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.OutputStream;
import java.math.RoundingMode;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.Random;

@Component
@Slf4j
public class TcpUtil {

    @Resource
    private ComErrAlarmMapper comErrAlarmMapper;

    /**充值
     *
     * @param ye
     * @param outputStream
     * @param MM
     * @param addr
     * @throws IOException
     */
    public void recharge(float ye , OutputStream outputStream , int MM ,int addr) throws IOException {
        byte[] k = floatToByteArray(ye);
        byte[] sendArray = new byte[21];
        sendArray[0] = (byte) addr;
        sendArray[1] = 16;
        sendArray[2] = 4;
        sendArray[3] = 0;
        sendArray[4] = 0;
        sendArray[5] = 6;
        sendArray[6] = 12;
        int s0, s1;
        Random rd = new Random();
        s0 = rd.nextInt(255);
        s1 = rd.nextInt(255);

        sendArray[7] = (byte) s0;
        sendArray[8] = (byte) s1;

        //取随机值的中间6位，再余24
        s0 = ((s0 % 128 - (s0 % 128 % 2)) / 2 % 24);
        s1 = ((s1 % 128 - (s1 % 128 % 2)) / 2 % 24);
        //byte mm = Get24JY(s0 * 4 + 3);
        sendArray[9 + Get24JY(s0 * 4 + 3)] = k[0];
        //mm = Get24JY(s0 * 4 + 2);
        sendArray[9 + Get24JY(s0 * 4 + 2)] = k[1];
        //mm = Get24JY(s0 * 4 + 1);
        sendArray[9 + Get24JY(s0 * 4 + 1)] = k[2];
        //mm = Get24JY(s0 * 4 + 0);
        sendArray[9 + Get24JY(s0 * 4 + 0)] = k[3];
        //特征字符
        k[0] = 0x43;// 67;
        k[1] = 0x5A;//90;
        k[2] = 0x6A;// 106;
        k[3] = 0x65;// 101;

        //用于获取24JY校验码
        sendArray[13 + Get24JY(s1 * 4)] = k[0];
        sendArray[13 + Get24JY(s1 * 4+1)] = k[1];
        sendArray[13 + Get24JY(s1 * 4+2)] = k[2];
        sendArray[13 + Get24JY(s1 * 4+3)] = k[3];

        byte[] crcJY = new byte[10];
        for (int i = 7; i < 17; i++)
        {
            crcJY[i - 7] = sendArray[i];
        }
        sendArray[17] = CRC16low(crcJY);
        sendArray[18] = CRC16High(crcJY);
        byte[] MD = new byte[4];

        MD[3] = 0x55;//85;
        MD[2] = (byte)0xAA;// 170;
        MD[1] = (byte)0xCC;// 204;
        MD[0] = 0x33;// 51;
        for (int i = 0; i < 4; i++)
        {
//            byte td, tm;
//            td = MD[i];
//            tm = (byte)(MM % 256);
            MD[i] = (byte)((MD[i] & 0xFF) ^ (MM % 256) );
            MM = MM / 256;
        }

        int j = 0;
        for (int i = 7; i < 19; i++)
        {
            sendArray[i] = (byte)((sendArray[i] & 0xFF) ^ (MD[j] & 0xFF));
            j++;
            j = j % 4;
        }
        //sendArray的7到18都是用来存储供方密码的01字段

        byte[] receData = new byte[19];

        for (int i = 0; i < 19; i++)
        {
            receData[i] = sendArray[i];
        }
        sendArray[19] = CRC16low(receData);
        sendArray[20] = CRC16High(receData);

        outputStream.write(sendArray);
        // 刷新输出流
        outputStream.flush();

    }

    /**
     * 修改单价
     * @param ye
     * @param outputStream
     * @param MM
     * @param addr
     * @throws IOException
     */
    public void priceChange(float ye , OutputStream outputStream , int MM ,int addr) throws IOException {
        DecimalFormat df3 = new DecimalFormat("#.000");
        df3.setRoundingMode(RoundingMode.HALF_UP);
        byte[] k = floatToByteArray(Float.parseFloat(df3.format(ye))*1000);
        byte[] sendArray = new byte[21];
        sendArray[0] = (byte) addr;
        sendArray[1] = 16;
        sendArray[2] = 4;
        sendArray[3] = 0;
        sendArray[4] = 0;
        sendArray[5] = 6;
        sendArray[6] = 12;
        int s0, s1;
        Random rd = new Random();
        s0 = rd.nextInt(255);
        s1 = rd.nextInt(255);

        sendArray[7] = (byte) s0;
        sendArray[8] = (byte) s1;

        //取随机值的中间6位，再余24
        s0 = ((s0 % 128 - (s0 % 128 % 2)) / 2 % 24);
        s1 = ((s1 % 128 - (s1 % 128 % 2)) / 2 % 24);
        //byte mm = Get24JY(s0 * 4 + 3);
        sendArray[9 + Get24JY(s0 * 4 + 3)] = k[0];
        //mm = Get24JY(s0 * 4 + 2);
        sendArray[9 + Get24JY(s0 * 4 + 2)] = k[1];
        //mm = Get24JY(s0 * 4 + 1);
        sendArray[9 + Get24JY(s0 * 4 + 1)] = k[2];
        //mm = Get24JY(s0 * 4 + 0);
        sendArray[9 + Get24JY(s0 * 4 + 0)] = k[3];
        //特征字符
//        k[0] = 0x43;// 67;
//        k[1] = 0x5A;//90;
//        k[2] = 0x6A;// 106;
//        k[3] = 0x65;// 101;
        //特征字符
        k[0] = 0x44;// 67;
        k[1] = 0x4A;//90;
        k[2] = 0x78;// 106;
        k[3] = 0x67;// 101;

        //用于获取24JY校验码
        sendArray[13 + Get24JY(s1 * 4)] = k[0];
        sendArray[13 + Get24JY(s1 * 4+1)] = k[1];
        sendArray[13 + Get24JY(s1 * 4+2)] = k[2];
        sendArray[13 + Get24JY(s1 * 4+3)] = k[3];

        byte[] crcJY = new byte[10];
        for (int i = 7; i < 17; i++)
        {
            crcJY[i - 7] = sendArray[i];
        }
        sendArray[17] = CRC16low(crcJY);
        sendArray[18] = CRC16High(crcJY);
        byte[] MD = new byte[4];

        MD[3] = 0x55;//85;
        MD[2] = (byte)0xAA;// 170;
        MD[1] = (byte)0xCC;// 204;
        MD[0] = 0x33;// 51;
        for (int i = 0; i < 4; i++)
        {
//            byte td, tm;
//            td = MD[i];
//            tm = (byte)(MM % 256);
            MD[i] = (byte)((MD[i] & 0xFF) ^ (MM % 256) );
            MM = MM / 256;
        }

        int j = 0;
        for (int i = 7; i < 19; i++)
        {
            sendArray[i] = (byte)((sendArray[i] & 0xFF) ^ (MD[j] & 0xFF));
            j++;
            j = j % 4;
        }
        //sendArray的7到18都是用来存储供方密码的01字段

        byte[] receData = new byte[19];

        for (int i = 0; i < 19; i++)
        {
            receData[i] = sendArray[i];
        }
        sendArray[19] = CRC16low(receData);
        sendArray[20] = CRC16High(receData);

        outputStream.write(sendArray);
        // 刷新输出流
        outputStream.flush();

    }


    /**
     *   开关阀门
     * @param status
     * @param outputStream
     * @param MM
     * @param addr
     * @throws IOException
     */
    public void valveChange(boolean status , OutputStream outputStream , int MM,int addr) throws IOException {
        float ye;
        if(status) {
            ye = 600;
        }else{
            ye = 400;
        }
        byte[] czData = new byte[12];
        byte[] k = floatToByteArray(ye);
        byte[] sendArray = new byte[21];
        sendArray[0] = (byte) addr; //仪表地址
        sendArray[1] = 16;
        sendArray[2] = 4;
        sendArray[3] = 0;
        sendArray[4] = 0;
        sendArray[5] = 6;
        sendArray[6] = 12;
        int s0, s1;
        Random rd = new Random();
        s0 = rd.nextInt(255);
        s1 = rd.nextInt(255);
        sendArray[7] = (byte) s0;
        sendArray[8] = (byte) s1;

        //取随机值的中间6位，再余24
        s0 = ((s0 % 128 - (s0 % 128 % 2)) / 2 % 24);
        s1 = ((s1 % 128 - (s1 % 128 % 2)) / 2 % 24);

        sendArray[9 + Get24JY(s0 * 4 + 3)] = k[0];
        //mm = Get24JY(s0 * 4 + 2);
        sendArray[9 + Get24JY(s0 * 4 + 2)] = k[1];
        //mm = Get24JY(s0 * 4 + 1);
        sendArray[9 + Get24JY(s0 * 4 + 1)] = k[2];
        //mm = Get24JY(s0 * 4 + 0);
        sendArray[9 + Get24JY(s0 * 4 + 0)] = k[3];
        //特征字符
        k[0] = 0x46;// 70;
        k[1] = 0x4D;//77;
        k[2] = 0x71;// 113;
        k[3] = 0x74;// 116;

        //用于获取24JY校验码
        sendArray[13 + Get24JY(s1 * 4)] = k[0];
        sendArray[13 + Get24JY(s1 * 4+1)] = k[1];
        sendArray[13 + Get24JY(s1 * 4+2)] = k[2];
        sendArray[13 + Get24JY(s1 * 4+3)] = k[3];

        byte[] crcJY = new byte[10];
        for (int i = 7; i < 17; i++)
        {
            crcJY[i - 7] = sendArray[i];
        }
        sendArray[17] = CRC16low(crcJY);  // 将 crcJY 数组的 CRC16 低位值赋值给 sendArray 数组的第17个元素
        sendArray[18] = CRC16High(crcJY);  // 将 crcJY 数组的 CRC16 高位值赋值给 sendArray 数组的第18个元素
        byte[] MD = new byte[4];

        MD[3] = 0x55;//85;
        MD[2] = (byte)0xAA;// 170;
        MD[1] = (byte)0xCC;// 204;
        MD[0] = 0x33;// 51;
        for (int i = 0; i < 4; i++)
        {
//            byte td, tm;
//            td = MD[i];
//            tm = (byte)(MM % 256);
            MD[i] = (byte)((MD[i] & 0xFF) ^ (MM % 256) );
            //异或操作
            MM = MM / 256;
        }

        int j = 0;
        for (int i = 7; i < 19; i++)
        {
            sendArray[i] = (byte)((sendArray[i] & 0xFF) ^ (MD[j] & 0xFF));
            j++;
            j = j % 4;
        }
        //sendArray的7到18都是用来存储供方密码的01字段

        byte[] receData = new byte[19];

        for (int i = 0; i < 19; i++)
        {
            receData[i] = sendArray[i];
        }
        sendArray[19] = CRC16low(receData);
        sendArray[20] = CRC16High(receData);

        outputStream.write(sendArray);
        // 刷新输出流
        outputStream.flush();
    }

    /**
     * 读取真实数据
     * @param outputStream
     * @param addr
     * @throws IOException
     */
    public void readData(OutputStream outputStream, int addr) throws IOException {
        // 创建发送数据数组
        byte[] sendArray = new byte[8];
        // 创建接收数据数组
        byte[] recData = new byte[6];

        // 设置发送数据数组的值
        sendArray[0] = (byte) addr;
        sendArray[1] = 3;
        sendArray[2] = 0;
        sendArray[3] = 0;
        sendArray[4] = 0;
        sendArray[5] = 54;

        // 将发送数据数组的值复制给接收数据数组
        for (int i = 0; i < 6; i++)
        {
            recData[i] = sendArray[i];
        }

        // 计算并设置发送数据数组的CRC校验值
        sendArray[6] = CRC16low(recData);
        sendArray[7] = CRC16High(recData);

//        for (byte b : sendArray) {
//            System.out.print(String.format("%02X ", b & 0xFF));
//        }


        try {
            // 向串口发送数据
//            log.info("开始读数据");
            outputStream.write(sendArray);
        }catch (SocketException e){
//            log.info("dtu连接中断");
//            log.info("dtu连接中断");
        }

    }

    public void readDataFour( OutputStream outputStream,int addr) throws IOException {
        // 创建发送数据数组
        byte[] sendArray = new byte[8];
        // 创建接收数据数组
        byte[] recData = new byte[6];

        // 设置发送数据数组的值
        sendArray[0] = (byte) addr;
        sendArray[1] = 3;
        sendArray[2] = 0;
        sendArray[3] = 0;
        sendArray[4] = 0;
        sendArray[5] = 16;

        // 将发送数据数组的值复制给接收数据数组
        for (int i = 0; i < 6; i++)
        {
            recData[i] = sendArray[i];
        }

        // 计算并设置发送数据数组的CRC校验值
        sendArray[6] = CRC16low(recData);

        sendArray[7] = CRC16High(recData);


        try {
            // 向串口发送数据
            outputStream.write(sendArray);
        }catch (SocketException e){
//            log.info("dtu连接中断");
        }

    }
    public void readDataValve( OutputStream outputStream,int addr) throws IOException {
        // 创建发送数据数组
        byte[] sendArray = new byte[8];
        // 创建接收数据数组
        byte[] recData = new byte[6];

        // 设置发送数据数组的值
        sendArray[0] = (byte) addr;
        sendArray[1] = 3;
        sendArray[2] = 0;
        sendArray[3] = 0;
        sendArray[4] = 0;
        sendArray[5] = 4;

        // 将发送数据数组的值复制给接收数据数组
        for (int i = 0; i < 6; i++)
        {
            recData[i] = sendArray[i];
        }

        // 计算并设置发送数据数组的CRC校验值
        sendArray[6] = CRC16low(recData);

        sendArray[7] = CRC16High(recData);

        try {
            // 向串口发送数据
            outputStream.write(sendArray);
        }catch (SocketException e){
//            log.info("dtu连接中断");
        }

    }

    public byte[] intToBytes2(int value)
    {
        byte[] src = new byte[4];
        src[0] = (byte) ((value>>24) & 0xFF);
        src[1] = (byte) ((value>>16)& 0xFF);
        src[2] = (byte) ((value>>8)&0xFF);
        src[3] = (byte) (value & 0xFF);
        return src;
    }

    public void writeDataValve( OutputStream outputStream,int addr,int t) throws IOException {
        // 创建发送数据数组
        byte[] sendArray = new byte[8];
        // 创建接收数据数组
        byte[] recData = new byte[6];

        byte[] src = intToBytes2(t);

        // 设置发送数据数组的值
        sendArray[0] = (byte) addr;
        sendArray[1] = 6;
        sendArray[2] = 0;
        sendArray[3] = 32;
        sendArray[4] = src[2];
        sendArray[5] = src[3];

        // 将发送数据数组的值复制给接收数据数组
        for (int i = 0; i < 6; i++)
        {
            recData[i] = sendArray[i];
        }

        // 计算并设置发送数据数组的CRC校验值
        sendArray[6] = CRC16low(recData);

        sendArray[7] = CRC16High(recData);

        // 发送数据
        outputStream.write(sendArray);


    }

    public void readDataFourPoint( OutputStream outputStream,int addr) throws IOException {
        // 创建发送数据数组
        byte[] sendArray = new byte[8];
        // 创建接收数据数组
        byte[] recData = new byte[6];

        // 设置发送数据数组的值
        sendArray[0] = (byte) addr;
        sendArray[1] = 3;
        sendArray[2] = 0;
        sendArray[3] = 45;
        sendArray[4] = 0;
        sendArray[5] = 1;

        // 将发送数据数组的值复制给接收数据数组
        for (int i = 0; i < 6; i++)
        {
            recData[i] = sendArray[i];
        }

        // 计算并设置发送数据数组的CRC校验值
        sendArray[6] = CRC16low(recData);
        sendArray[7] = CRC16High(recData);

        // 向串口发送数据
        outputStream.write(sendArray);
        log.info("发送成功");

    }

    /**
     * 对预收费表读到的真实数据进行处理和保存
     * @param ch
     * @param realdata
     * @return
     */
    public double[] process_realdata(byte[] ch, Realdata realdata){
        double[] f = new double[17];
        // 创建一个长度为111的字节数组
        byte[] recData = new byte[111];
        // 将ch数组中的前111个字节复制到recData数组中
        for (int i = 0; i < 111; i++)
        {
            recData[i] = ch[i];
        }

        // 计算CRC16校验码的低位
        byte ccl = CRC16low(recData);
        // 计算CRC16校验码的高位
        byte cch = CRC16High(recData);

        // 如果低位CRC校验码等于第111个字节且高位CRC校验码等于第112个字节
        if (CRC16low(recData) == ch[111] && CRC16High(recData) == ch[112]) {
            // 将recData数组中的每两个相邻字节交换位置
            for (int i = 3; i < 111; i = i + 2) {
                byte tempD = ch[i];
                ch[i] = ch[i + 1];
                ch[i + 1] = tempD;
            }

            // 设置为小端字节序
            ByteBuffer bb = ByteBuffer.wrap(ch).order(ByteOrder.LITTLE_ENDIAN);

            for (int j = 0; j < 9; j++) {
                f[j] = bb.getFloat(j * 4 + 3);
            }

            f[9] =  ch[9 * 4 + 3];
            f[10] = ch[10 * 4 + 3];
            f[11] = (ch[11 * 4 + 3 + 1] * 256 + ch[11 * 4 + 3]);
            f[12] = ch[12 * 4 + 3];
            f[13] = bb.getDouble(13 * 4 + 3);
            f[14] = bb.getDouble(63);
            f[15] = bb.getDouble(71);
            f[16] = bb.getDouble(79);

            if (ch[94] != 0 && ch[93] != 0 && ch[92] != 0 && ch[91] != 0){
                LocalDateTime ltDnTime = LocalDateTime.of((ch[94] & 0xff) % 128 * 256 + (ch[93]&0xff),  ch[92], ch[91],  ch[89], ch[88],  ch[87]);
                realdata.setLtDnTime(ltDnTime);
            }

            if (ch[102] != 0 && ch[101] != 0 && ch[100] != 0 && ch[99] != 0){
                LocalDateTime ltUpTime = LocalDateTime.of((ch[102] &0xff) * 256 + (ch[101]&0xff), (int) ch[100], (int) ch[99], (int) ch[97], (int) ch[96], (int) ch[95]);
                realdata.setLtUpTime(ltUpTime);
            }


            if (ch[110] != 0 && ch[109] != 0 && ch[108] != 0 && ch[107] != 0){
                LocalDateTime paraTime = LocalDateTime.of((ch[110] &0xff) * 256 + (ch[109]&0xff), (int) ch[108], (int) ch[107], (int) ch[105], (int) ch[104], (int) ch[103]);
                realdata.setParaTime(paraTime);
            }
        }

        return f;
    }


    public double[] processRealdataFour(byte[] ch, Realdata realdata){
        double[] f = new double[4];
        // 创建一个长度为35的字节数组
        byte[] recData = new byte[35];

        // 将ch数组中的所有字节复制到recData数组中
        for (int i = 0; i < 35; i++)
        {
            recData[i] = ch[i];
        }

        // 如果低位CRC校验码等于第36个字节且高位CRC校验码等于第37个字节
        if (CRC16low(recData) == ch[35] && CRC16High(recData) == ch[36]) {

            for (int i = 3; i < 35; i = i + 2) {
                byte tempD = ch[i];
                ch[i] = ch[i + 1];
                ch[i + 1] = tempD;
            }
            // 设置为小端字节序
            ByteBuffer bb = ByteBuffer.wrap(ch).order(ByteOrder.LITTLE_ENDIAN);


            for (int j = 0; j < 4; j++) {
                f[j] = bb.getShort(j * 2 + 3);
//                System.out.print(f[j] + "  ");
            }

        }
        return f;
    }


    /**
     * 处理阀门收到的实时数据，转化成double数组
     * @param ch
     * @return
     */
    public double[] processReadDataValve(byte[] ch){
        double[] f = new double[2];
        // 创建一个长度为35的字节数组
        byte[] recData = new byte[11];

        // 将ch数组中的所有字节复制到recData数组中
        for (int i = 0; i < 11; i++)
        {
            recData[i] = ch[i];
        }

        if (CRC16low(recData) == ch[11] && CRC16High(recData) == ch[12]) {

            for (int i = 3; i < 11; i = i + 2) {
                byte tempD = ch[i];
                ch[i] = ch[i + 1];
                ch[i + 1] = tempD;
            }
            // 设置为小端字节序
            ByteBuffer bb = ByteBuffer.wrap(ch).order(ByteOrder.LITTLE_ENDIAN);


            for (int j = 0; j < 2; j++) {
                f[j] = bb.getFloat(j * 4 + 3);
            }

        }
        return f;
    }

    public double[] processWriteDataValve(byte[] ch){
        double[] f = new double[2];
        // 创建一个长度为6的字节数组
        byte[] recData = new byte[6];

        // 将ch数组中的所有字节复制到recData数组中
        for (int i = 0; i < 6; i++)
        {
            recData[i] = ch[i];
        }

        if (CRC16low(recData) == ch[6] && CRC16High(recData) == ch[7]) {

            for (int i = 3; i < 6; i = i + 2) {
                byte tempD = ch[i];
                ch[i] = ch[i + 1];
                ch[i + 1] = tempD;
            }
            // 设置为小端字节序
            ByteBuffer bb = ByteBuffer.wrap(ch).order(ByteOrder.LITTLE_ENDIAN);


            for (int j = 0; j < 2; j++) {
                f[j] = bb.getShort(j * 2 + 2);
            }

        }
        return f;
    }
    /**
     * 把float转化为byte数组
     * @param value
     * @return
     */
    private  byte[] floatToByteArray(float value) {
        ByteBuffer buffer = ByteBuffer.allocate(Float.BYTES).order(ByteOrder.LITTLE_ENDIAN);
        buffer.putFloat(value);
        return buffer.array();
    }

    /**
     * 私有方法：计算CRC16校验码的低位
     * @param data
     * @return
     */
    private byte CRC16low(byte[] data)
    {
        byte CRC16Hi, CRC16Lo;
        int i;
        int iIndex;
        CRC16Hi = (byte)0xFF;
        CRC16Lo = (byte)0xFF;


        // 遍历数据数组
        for (i = 0; i < data.length; i++)
        {
            iIndex = (CRC16Lo & 0xFF) ^ (data[i] & 0xFF);
            int unsignedResult = iIndex & 0xFF;
            CRC16Lo = (byte)((CRC16Hi & 0xFF) ^ (GetCRCLo(unsignedResult) & 0xFF) );
            CRC16Hi = GetCRCHi(unsignedResult);
        }

        return CRC16Lo;
    }

    /**
     * 私有方法：计算CRC16校验码的高位
     * @param data
     * @return
     */
    private byte CRC16High(byte[] data)
    {
        byte CRC16Hi, CRC16Lo;
        int i;
        int iIndex;
        CRC16Hi = (byte)0xFF;
        CRC16Lo = (byte)0xFF;
        // 遍历数据数组
        for (i = 0; i < data.length; i++)
        {
            iIndex = (CRC16Lo & 0xFF) ^ (data[i] & 0xFF);
            int unsignedResult = iIndex & 0xFF;
            CRC16Lo = (byte)((CRC16Hi & 0xFF) ^ (GetCRCLo(unsignedResult) & 0xFF));
            CRC16Hi = GetCRCHi(unsignedResult);
        }
        return CRC16Hi;
    }

    /**
     * 获取CRCLo函数，用于获取低位CRC
     * @param Ind
     * @return
     */
    private byte GetCRCLo(int Ind)
    {
        int[] Ichoose0 = new int[]{0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80,0x41, 0x0,
                0xC1, 0x81, 0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x0, 0xC1,
                0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81,
                0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40,
                0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0,
                0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1,
                0x81, 0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81,
                0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41,0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40,
                0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x1,
                0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x0, 0xC1,
                0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40, 0x1, 0xC0, 0x80, 0x41, 0x1, 0xC0, 0x80, 0x41, 0x0, 0xC1, 0x81, 0x40};
        byte[] Ichoose = intToByte(Ichoose0);
        return Ichoose[Ind] ;
    }

    /**
     * 获取24JY函数，用于获取24JY校验码
     * @param Ind
     * @return
     */
    private byte Get24JY(int Ind)
    {
        int[] Ichose0 = new int[]{0x00,0x01,0x02,0x03,0x00,0x01,0x03,0x02,
                0x00,0x02,0x03,0x01,0x00,0x02,0x01,0x03,
                0x00,0x03,0x01,0x02,0x00,0x03,0x02,0x01,
                0x01,0x02,0x00,0x03,0x01,0x02,0x03,0x00,
                0x01,0x00,0x03,0x02,0x01,0x00,0x02,0x03,
                0x01,0x03,0x02,0x00,0x01,0x03,0x00,0x02,
                0x02,0x01,0x00,0x03,0x02,0x01,0x03,0x00,
                0x02,0x00,0x03,0x01,0x02,0x00,0x01,0x03,
                0x02,0x03,0x01,0x00,0x02,0x03,0x00,0x01,
                0x03,0x01,0x00,0x02,0x03,0x01,0x02,0x00,
                0x03,0x02,0x01,0x00,0x03,0x02,0x00,0x01,
                0x03,0x00,0x01,0x02,0x03,0x00,0x02,0x01,
        };
        byte[] Ichose = intToByte(Ichose0);
        return Ichose[Ind];
    }

    /**
     * 获取CRCHi函数，用于获取高位CRC
     * @param Ind
     * @return
     */
    private byte GetCRCHi(int Ind)
    {

        int[] Ichose0 = new int[] {0x0, 0xC0, 0xC1, 0x1, 0xC3, 0x3, 0x2, 0xC2, 0xC6, 0x6, 0x7, 0xC7, 0x5, 0xC5, 0xC4, 0x4, 0xCC, 0xC, 0xD, 0xCD, 0xF, 0xCF,
                0xCE, 0xE, 0xA, 0xCA, 0xCB, 0xB, 0xC9, 0x9, 0x8, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C,
                0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2,
                0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8,
                0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6,
                0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64,
                0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A,
                186, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70,
                0xB0, 0x50, 0x90,0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E,
                0x5E, 0x5A, 0x9A,0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C,
                0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 };
        byte[] Ichose = intToByte(Ichose0);

        return Ichose[Ind];
    }

    /**
     * 将int类型的数组转成byte的数组
     * @param array
     * @return
     */
    private byte[] intToByte(int[] array){
        byte[] res =  new byte[array.length];
        for(int i =0;i<array.length;i++){
            res[i] = (byte)array[i];
        }
        return  res;
    }

}
